package pro.shushi.pamirs.hr.core.auth;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.auth.api.entity.node.ActionPermissionNode;
import pro.shushi.pamirs.auth.api.entity.node.PermissionNode;
import pro.shushi.pamirs.auth.api.enumeration.ResourcePermissionSubtypeEnum;
import pro.shushi.pamirs.auth.api.extend.load.PermissionNodeLoadExtendApi;
import pro.shushi.pamirs.auth.api.helper.AuthHelper;
import pro.shushi.pamirs.auth.api.loader.entity.PermissionLoadContext;
import pro.shushi.pamirs.boot.base.enmu.ActionTypeEnum;
import pro.shushi.pamirs.boot.base.model.Action;
import pro.shushi.pamirs.boot.base.model.ServerAction;
import pro.shushi.pamirs.boot.web.loader.path.ResourcePath;
import pro.shushi.pamirs.core.common.query.QueryActions;
import pro.shushi.pamirs.hr.api.model.auth.AppAuthResource;
import pro.shushi.pamirs.hr.api.tmodel.AuthResourceTransient;
import pro.shushi.pamirs.meta.common.spi.SPI;
import pro.shushi.pamirs.meta.common.util.ListUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 权限数据 加载扩展
 *
 * @author shushi
 */
@Component
@Order(80)
@SPI.Service("HrSimplePermissionNodeLoadExtend")
public class HrSimplePermissionNodeLoadExtend implements PermissionNodeLoadExtendApi {

    @Override
    public List<PermissionNode> buildRootPermissions(PermissionLoadContext loadContext, List<PermissionNode> nodes) {
        List<AppAuthResource> authResources = new AppAuthResource().queryList();
        if (CollectionUtils.isEmpty(authResources)) {
            return nodes;
        }

        List<AppAuthResource> validAuthResources = authResources.stream().filter(one -> one.getMenuId()!=null).collect(Collectors.toList());
        Map<Long/**MenuId*/, List<AppAuthResource>> authResourceByMenu = validAuthResources.stream()
                .collect(Collectors.groupingBy(AppAuthResource::getMenuId));
        QueryActions<ServerAction> queryActions = new QueryActions<>(ActionTypeEnum.SERVER);
        validAuthResources.stream().forEach(resource -> {
            queryActions.add(AuthResourceTransient.MODEL_MODEL, resource.getResUnique());
        });
        List<ServerAction> serverActions = queryActions.query();
        if (CollectionUtils.isEmpty(serverActions)) {
            return nodes;
        }

        addCustomAction(nodes, authResourceByMenu, serverActions);

        return nodes;
    }

    private void addCustomAction(List<PermissionNode> nodes, Map<Long/**MenuId*/, List<AppAuthResource>> authResourceByMenu, List<ServerAction> allServerActions) {
        if (CollectionUtils.isEmpty(nodes)) {
            return;
        }

        for (PermissionNode node : nodes) {
            if (ResourcePermissionSubtypeEnum.MENU.equals(node.getNodeType())) {
                List<AppAuthResource> authResources = authResourceByMenu.get(node.getResourceId());
                if (CollectionUtils.isNotEmpty(authResources)) {
                    List<Long> resourceIds = ListUtils.transform(authResources, AppAuthResource::getResourceId);
                    List<ServerAction> serverActions = allServerActions.stream().filter(sa -> resourceIds.contains(sa.getId())).collect(Collectors.toList());
                    createActionNodes(serverActions, node);
                }
            }
            addCustomAction(node.getNodes(), authResourceByMenu, allServerActions);
        }
    }

    private void createActionNodes(List<ServerAction> actions, PermissionNode parentNode) {
        if (CollectionUtils.isEmpty(actions)) {
            return;
        }

        for (int i = 0; i < actions.size(); i++) {
            ServerAction action = actions.get(i);
            PermissionNode target = _createActionNode(action, parentNode);

            if (target == null) {
                return;
            }
            if (CollectionUtils.isNotEmpty(parentNode.getNodes())) {
                parentNode.getNodes().add(target);
            } else {
                parentNode.setNodes(Collections.singletonList(target));
            }
        }
    }

    private ActionPermissionNode _createActionNode(Action action, PermissionNode parentNode) {
        ActionPermissionNode node = createActionNode((ServerAction) action, parentNode);
        if (node == null) {
            return null;
        }
        node.setPath("/" + action.getModel() + "/" + action.getName());
        return node;
    }

    private static ActionPermissionNode createActionNode(ServerAction action, PermissionNode parentNode) {
        Long actionId = action.getId();
        ActionPermissionNode node = new ActionPermissionNode();
        node.setNodeType(ResourcePermissionSubtypeEnum.SERVER_ACTION);
        node.setId(actionId.toString());
        node.setHasNext(Boolean.FALSE);
        node.setCanAccess(Boolean.FALSE);
        node.setCanAllot(Boolean.TRUE);
        node.setResourceId(actionId);
        node.setPath(ResourcePath.generatorPath(action.getModel(), action.getName()));
        node.setDisplayValue(AuthHelper.getActionDisplayValue(action));
        node.setModel(action.getModel());
        node.setAction(action.getName());
        node.setActionType(action.getActionType());
        if (parentNode != null) {
            node.setParentId(parentNode.getId());
            node.setParent(parentNode);
        }

        return node;
    }

}
